// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <pthread.h>
#include "primitives.h"

//#include "/home/long/snap/flutter/common/flutter/bin/cache/dart-sdk/include/dart_api.h"
//#include "/home/long/snap/flutter/common/flutter/bin/cache/dart-sdk/include/dart_api_dl.h"

//Dart_Port send_port;

int main() {
    printf("3 + 5 = %d\n", sum(3, 5));
    int *mult = multiply(3, 5);
    printf("3 * 5 = %d\n", *mult);
    free(mult);
    int sub_num = 3;
    printf("3 - 5 = %d\n", subtract(&sub_num, 5));
    return 0;
}

int incremental(int i) {
    return i + 1;
}

int sum(int a, int b) {
    return a + b;
}

int *multiply(int a, int b) {
    // Allocates native memory in C.
    int *mult = (int *) malloc(sizeof(int));
    *mult = a * b;
    return mult;
}

void free_pointer(int *int_pointer) {
    // Free native memory in C which was allocated in C.
    free(int_pointer);
}

int subtract(int *a, int b) {
    return *a - b;
}

// 调用dart函数
void ping(pong callback) {
    printf("ping\n");
    callback(1);//sync call
}

void async_ping(Dart_Port_DL port) {//Dart_Port_DL
    printf("async ping port: %ld\n", port);
    __startThread(port);
}

DART_EXPORT intptr_t

InitDartApiDL(void *data) {
    return Dart_InitializeApiDL(data);
}

// 线程标识符
pthread_t pid;
// 全局互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 线程退出标志
int sign = 1;
int count = 0;

// 1. 定义线程处理函数
void *__threadHandler(void *args) {
    Dart_Port_DL send_port = (Dart_Port_DL) args;
    printf("This is a pthread running at port:%ld\n", send_port);
    fflush(stdout);
    while (sign) {
        /* 锁定互斥锁*/
        pthread_mutex_lock(&mutex);
        count++;
        int result;
        if (count % 2 == 0) {
            Dart_CObject dart_str;
            dart_str.type = Dart_CObject_kString;
            dart_str.value.as_string = "pong";
            result = Dart_PostCObject_DL(send_port, &dart_str);
        } else {
            Dart_CObject dart_int;
            dart_int.type = Dart_CObject_kInt32;
            dart_int.value.as_int32 = count;
            result = Dart_PostCObject_DL(send_port, &dart_int);
        }
        if (!result) {
            printf("C Posting message to port failed. %d\n", result);
            fflush(stdout);
            sign == 0;
            pthread_mutex_unlock(&mutex);
            return 0;
        }
        sleep(1);
        /* 解锁互斥锁*/
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
    //or
//    Dart_Handle sendPort = Dart_NewSendPort(dart_port);
//    // Check if creating the SendPort was successful
//    if (!Dart_IsError(sendPort)) {
//        if (Dart_PostCObject(dart_port, &message)) {
//            printf("Message sent\n");
//            fflush(stdout);
//        } else {
//            printf("Failed to create SendPort\n");
//            fflush(stdout);
//        }
//    }
}

// 2. 启动线程
void __startThread(Dart_Port_DL port) {
    printf("sign: %d\n", sign);
    // runtime_entry.cc: 4083: error: Cannot invoke native callback outside an isolate.
    if (pthread_create(&pid, NULL, __threadHandler, (void *) port) != 0) {
        fprintf(stderr, "Error creating thread\n");
        exit(1);
    }
}

// 3. 停止线程
void __stopThread() {
    sign = 0;
    pthread_mutex_destroy(&mutex);
    // 加入线程以确保其资源被正确释放
    pthread_join(pid, NULL);
}
